package com.defense.chat;
/**
* @类名  Clients.java
* @作者  jinbanglong
* @版本  V1.0
* @日期  2019年6月27日-下午7:57:33
* @描述  
*
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.Scanner;

import com.defense.model.User;
import com.defense.util.Regex;

public class Clients {
	
   public static void main(String[] args) {
	   
	   User user=login();
	   if("在线".equals(user.getStatus())) {
		   System.out.println("不可重复登录");
		   return;
	   }
	   if("reg".equals(user.getuName())) {
		   user = register();
	   }
	   if("exit".equals(user.getuName())) {
		   System.out.println("您已退出系统");
		   return;
	   }
	   //聊天记录类
	   ChatLog log = new ChatLog();
      try {
         Socket s = new Socket("127.0.0.1",8888);
         //构建IO
         InputStream is = s.getInputStream();
         OutputStream os = s.getOutputStream();
         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
         BufferedReader br = new BufferedReader(new InputStreamReader(is));
         DataOutputStream dos = new DataOutputStream(os);
         Thread send = new Thread(new Send(bw,user,log,dos));
         send.start();
         new Thread(new Receive(br,user,log)).start();
         
      } catch (UnknownHostException e) {
    	  user.changeStatus(user.getuName(), "离线");
         e.printStackTrace();
      } catch (IOException e) {
    	  user.changeStatus(user.getuName(), "离线");
         e.printStackTrace();
      }finally {
    	  
      }
   }
   public static User register() {
	   Scanner sc = new Scanner(System.in);
	   while(true) {
		   User user = new User();
		   System.out.println("注册用户名["+Regex.pwdMsg+"]:");
		   String uName;
		   while(true) {
			   uName = sc.nextLine();
			   if("exit".equals(uName)) {
				   user.setuName(uName);
				   return user;
			   }
			   if(user.checkRepeat(uName)) {
				   System.err.println("用户名已存在，换一个吧");
				   continue;
			   }
			   if(!uName.matches(Regex.uName)) {//正则验证用户名
				   System.err.println(Regex.uNameMsg);
			   }else {
				   break;
			   }
		   }
		   
		   System.out.println("注册密码["+Regex.pwdMsg+"]:");
		   String pwd;
		   while(true) {
			   pwd = sc.nextLine();
			   if("exit".equals(pwd)) {
				   user.setuName(pwd);
				   return user;
			   }
			   if(!pwd.matches(Regex.pwd)) {//正则验证用户名密码
				   System.err.println(Regex.pwdMsg);
			   }else {
				   break;
			   }
		   }
		   user.setNickName(uName);
		   user.setuName(uName);
		   user.setPwd(pwd);
		   user = user.register(user);
		   if(user==null) {
			   System.out.println("注册失败");
			   continue;
		   }
		   return user;
	   }
   }
   
   public static User login() {
	   Scanner sc = new Scanner(System.in);
	   String uName;
	   String pwd;
	   while(true) {
		   User user = new User();
		   System.out.println("用户名：");
		   while(true) {
			   uName = sc.nextLine();
//			   System.out.println(uName);
			   user.setuName(uName);
			   if("exit".equals(uName)||"reg".equals(uName)) {
				   return user;
			   }else if(!uName.matches(Regex.uName)) {//正则验证用户名
				   System.err.println(Regex.uNameMsg);
			   }else {
				   break;
			   }
		   }
		  
		   System.out.println("密码：");
		   while(true) {
			   pwd = sc.nextLine();
			   if("exit".equals(pwd)||"reg".equals(pwd)) {
				   user.setuName(pwd);
				   return user;
			   }
			   if(!pwd.matches(Regex.pwd)) {//正则验证用户名密码
				   System.err.println(Regex.pwdMsg);
			   }else {
				   break;
			   }
		   }
		   
		   try {
				user = user.login(uName,pwd);
				if(user==null) {
					System.err.println("用户名或密码错误，请重新输入");
					continue;
				}
				return user;
			} catch (Exception e) {
//				e.printStackTrace();
				System.out.println("登录异常，请重新登录");
				continue;
			}
	   }
	   
   }
   
}
class Send implements Runnable{
	User user;
	ChatLog log;
	BufferedWriter bw;
	DataOutputStream dos;
	public Send(BufferedWriter bw,User user,ChatLog log,DataOutputStream dos) {
		this.bw = bw;
		this.user = user;
		this.log = log;
		this.dos=dos;
		try {
			send(user.getuName());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void run() {
		Scanner sc = new Scanner(System.in);
		while(true) {
			String msg = sc.nextLine();
			msg = msg.replaceAll("：", ":");//统一冒号为英文
			if(msg.equals("")) {
				continue;
			}
			if(msg.startsWith("@")) {//私聊需要检测，用户名有效性
				//@jin:
				//@jin-f:
				
				String strMsg = msg.substring(1, msg.indexOf(":"));
				String[] split = strMsg.split("-");
				if(!user.check(split[0])) {
					System.err.println("用户不存在，或已离线");
					continue;
				}
				
			}
			if("exit".equals(msg)) {
				try {
					send(msg);
				} catch (IOException e) {
					System.err.println("输入指令有误，请检查");
					continue;
//					e.printStackTrace();
				}
				 user.changeStatus(user.getuName(), "离线");
				 System.out.println("您已离开聊天室");
				break;
			}
			//查询聊天记录
			if(msg.matches(Regex.see)) {//  S:jinl:2019-06-30
				String[] msgArr = msg.split(":");
				if("group".equals(msgArr[1])) {//查询群消息
					String type="group";
					String uName="only";//群，目前只有一个，固定一个名字
					log.getLog(user.getuName(), type, uName, msgArr[2]);
				}else{
					String type="whisper";
					log.getLog(user.getuName(), type, msgArr[1], msgArr[2]);
				}
				continue;
			}
			//下载文件
			if(msg.startsWith("down-")) {
				download(msg.substring(5));
				continue;
			}
			try {
				send(msg);
			} catch (IOException e) {
				//e.printStackTrace();
				System.err.println("输入指令有误，请检查");
				return;
			}
		}
		
		
	}
	public void send(String msg) throws IOException {
		//发送文件
		//群聊-f:
		//@私聊-f
		int endIndex=msg.indexOf(":");
		if(endIndex!=-1) {
			String name = msg.substring(0, endIndex);
			if(name.matches(Regex.fileGroup)||name.matches(Regex.fileCommand)) {//文件发送命令
				String path=msg.substring(endIndex+1);
				//String[] file = path.split(",");//多文件
//				System.out.println(path);
				bw.write(name+":\n");
		        bw.flush();
				upload(path);
			} 
		}
		
		bw.write(msg+"\n");
        bw.flush();
        try {
			log.saveLog(this.user.getuName(), "out", msg);//存储聊天记录
		} catch (Exception e) {
			System.err.println("输入指令有误，请检查");
			return;
		}
         
         
	}
	
	//上传方法，目前只能单张图片上传
	public void upload(String path) {
        
        try {
        	System.out.println(path);
    		File f= new File(path);
    		if(!f.exists()) {
    			return;
    		}
        	DataInputStream dis = new  DataInputStream(new FileInputStream(path));
        	dos.writeUTF(f.getName());//文件名
        	dos.writeLong(f.length());//文件大小
        	
        	byte[] b =new byte[1024];
        	int len;
        	while((len=dis.read(b))!=-1) {
        		dos.write(b, 0, len);
        		dos.flush();
        	}
        	dis.close();
        } catch (IOException e) {
//        	e.getStackTrace();
        	System.err.println("文件格式不正确,或不存在");
        	return;
        }
	}
	//下载方法
	public void download(String urls) {
//		System.out.println(urls);
		InputStream is=null;
		FileOutputStream  fos=null;
		try {
			if(urls==null||!urls.matches(Regex.url)) {
				System.out.println(Regex.urlMsg);
				return;
			}
			URL url = new URL(urls);
			URLConnection conn = url.openConnection();
			is = conn.getInputStream();
			
			String fileName = url.getFile();
			//      /img/1.jpg
			fileName=fileName.substring(fileName.lastIndexOf("/"));
//			System.out.println(fileName);
			//下载路径
			String path = "D://web/download"+fileName;
			File file = new File(path);
			
			fos = new FileOutputStream(file);
			byte[] b = new byte[1024];
			int len ;
			while((len=is.read(b))!=-1) {
				fos.write(b, 0, len);
			}
			fos.close();
			is.close();
			System.out.println("下载完成!");
			System.out.println("文件存储路径："+path);
			
		} catch (IOException e) {
			System.err.println("文件下载错误，检查服务");
			return;
//			e.printStackTrace();
		}finally {
			try {
				if(is!=null) {
					is.close();
				}
				if(fos!=null) {
					fos.close();
				}
			} catch (IOException e) {
				System.err.println("异常关闭");
//				e.printStackTrace();
			}
		}
		
	}
}
class Receive implements Runnable{
	User user;
	ChatLog log;
	BufferedReader br;
	public Receive(BufferedReader br,User user,ChatLog log) {
		this.br = br;
		this.user = user;
		this.log = log;
	}
	@Override
	public void run() {
		while(true) {
			try {
				receive();
			} catch (IOException e) {
				System.err.println("数据格式有误");
				continue;
//				e.printStackTrace();
			}
		}
	}
	public void receive() throws IOException {
		String msg = br.readLine();
        System.out.println(msg);
        
        if(!msg.startsWith("上传进度")) {
        	if(msg.startsWith("@")) {
                log.saveLog(this.user.getuName(), "out", msg);//存储聊天记录
            }else {
            	log.saveLog(this.user.getuName(), "in", msg);//存储聊天记录
            }
        }
        
	}
	
}